package org.grill.clovercash;

import java.text.NumberFormat;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.ViewPart;
import org.grill.clovercash.accounts.Account;
import org.grill.clovercash.accounts.Account.IDeltaListener;

public class AccountListView extends ViewPart {
	public static final String ID = "org.grill.clovercash.accountlistview";

	private TreeViewer viewer;

	/**
	 * The content provider class is responsible for providing objects to the
	 * view. It can wrap existing objects in adapters or simply return objects
	 * as-is. These objects may be sensitive to the current input of the view,
	 * or ignore it and always show the same content (like Task List, for
	 * example).
	 */
	public class ViewContentProvider implements ITreeContentProvider, IStructuredContentProvider, IDeltaListener {
		public ViewContentProvider() {
			CloverCashUIPlugin.getDefault().getRootAccount().addListener(this);
		}


		public void inputChanged(Viewer v, Object oldInput, Object newInput) {

		}


		public void dispose() {
		}

		public Object[] getElements(Object parent) {
//			System.out.println("Getting elements for " + parent);
			return CloverCashUIPlugin.getDefault().getRootAccount().getChildren().toArray();
		}

		public Object[] getChildren(Object parentElement) {
			Account a = (Account) parentElement;
			return a.getChildren().toArray();
		}

		public Object getParent(Object element) {
			Account a = (Account) element;
			return a.getParent();
		}

		public boolean hasChildren(Object element) {
			Account a = (Account) element;
			return !a.getChildren().isEmpty();
		}

		public void add(org.grill.clovercash.accounts.Account.DeltaEvent event) {
//			if (event.receiver() instanceof Account)
//			System.out.println("Refreshing....");
			viewer.refresh(true);
		}

		public void remove(org.grill.clovercash.accounts.Account.DeltaEvent event) {
			viewer.refresh();
		}
		
	}

	class ViewLabelProvider extends LabelProvider implements ITableLabelProvider {
		@Override
		public String getText(Object obj) {
//			System.out.println("Asking about " + obj);
			Account account = (Account) obj;
			return account.getName(); 
		}

		

		public Image getColumnImage(Object element, int columnIndex) {
			// TODO Auto-generated method stub
			return null;
		}



		public String getColumnText(Object element, int columnIndex) { 
			try {
				String accountText = getAccountText(element, columnIndex);
//				System.out.println("accountText: " + columnIndex + ", " + accountText);
				return accountText;
			} catch (Exception e) {
				e.printStackTrace();
				return "foo";
			}
		}



		private String getAccountText(Object element, int columnIndex) {
			if (columnIndex == 0) 
				return getText(element);
			Account a = (Account) element;
			
			if (columnIndex == 4)
				return a.getDescription();  
			
			
			NumberFormat format = NumberFormat.getCurrencyInstance();
			
			if (columnIndex == 1)
				return format.format(a.getTotal());
			if (columnIndex == 2)
				return format.format(a.getCumTotal());
			if (columnIndex == 3)
				return format.format(a.getReconciledTotal(true));
			
			return "ASDFASDF";
		}
	}

    private void hookContextMenu() {
        MenuManager menuManager = new MenuManager("#PopupMenu");
        menuManager.setRemoveAllWhenShown(true);
        menuManager.addMenuListener(new IMenuListener() {
                public void menuAboutToShow(IMenuManager manager) {
                        AccountListView.this.fillContextMenu(manager);
                }
        });
        Menu menu = menuManager.createContextMenu(viewer.getControl());
        
        viewer.getControl().setMenu(menu);
        getSite().registerContextMenu(menuManager, viewer);
}

	
	protected void fillContextMenu(IMenuManager manager) {
		manager.add(new Separator("new"));
		manager.add(new EditAccountAction(this));
		manager.add(new ReconcileAccountAction(this));
	}


	/**
	 * This is a callback that will allow us to create the viewer and initialize
	 * it.
	 */
	public void createPartControl(Composite parent) {
		viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL
				| SWT.V_SCROLL);
		
		TreeColumn nameCol = new TreeColumn(viewer.getTree(), SWT.LEFT, 0);
		nameCol.setText("Account");
		nameCol.setWidth(200);
		
		TreeColumn balCol = new TreeColumn(viewer.getTree(), SWT.RIGHT, 1);
		balCol.setText("Balance");
		balCol.setWidth(100);
		
		TreeColumn cumCol = new TreeColumn(viewer.getTree(), SWT.RIGHT, 2);
		cumCol.setText("Cum Bal");
		cumCol.setWidth(100);
		
		TreeColumn recCol = new TreeColumn(viewer.getTree(), SWT.RIGHT, 3);
		recCol.setText("Rec Bal");
		recCol.setWidth(100);
		
		TreeColumn descCol = new TreeColumn(viewer.getTree(), SWT.LEFT, 4);
		descCol.setText("Description");
		descCol.setWidth(200);

		viewer.getTree().setHeaderVisible(true);
		viewer.setAutoExpandLevel(2);
		
		viewer.setContentProvider(new ViewContentProvider());
		viewer.setLabelProvider(new ViewLabelProvider());
		viewer.setInput(CloverCashUIPlugin.getDefault().getRootAccount());
		
		hookContextMenu();
		contributeToActionBars();
		
		viewer.addDoubleClickListener(new IDoubleClickListener() {
			public void doubleClick(DoubleClickEvent event) {
				openLedgerView();
			}
		});
	}

	private void contributeToActionBars() {
		IActionBars bars = getViewSite().getActionBars();
		fillLocalToolBar(bars.getToolBarManager());
	}


	private void fillLocalToolBar(IToolBarManager toolBarManager) {
		toolBarManager.add(new AddAccountAction(this));
		toolBarManager.add(new Action("Remove Account", CloverCashUIPlugin.getImageDescriptor("remove.gif")) {
			@Override
			public void run() {
				IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
				if (selection.isEmpty())
					return;
				boolean b = MessageDialog.openConfirm(getSite().getShell(), "Really Remove?", "Are you really super-duper extra-sure you want to delete this?");
				if (b) {
					Account a = (Account) selection.getFirstElement();
					a.getParent().remove(a);
				}
			}
		});
	}

	

	/**
	 * Passing the focus request to the viewer's control.
	 */
	public void setFocus() {
		viewer.getControl().setFocus();
	}


	public TreeViewer getViewer() {
		return viewer;
	}


	private void openLedgerView() {
		try {
			IStructuredSelection sel = (IStructuredSelection) viewer.getSelection();
			if (sel.isEmpty())
				return;
			
			Account a = (Account) sel.getFirstElement(); 
			
			IViewPart part = getSite().getPage().showView(AccountLedgerView.ID, a.getDisplayName(), IWorkbenchPage.VIEW_ACTIVATE);
			AccountLedgerView view = (AccountLedgerView) part;
			if (!view.isInitialized()) { 
				view.setAccount(a);
			}
		} catch (PartInitException e) {
			e.printStackTrace();
		} catch (Throwable e) {
			e.printStackTrace();
		}
	}
}